/*
 * 作者: junmu
 * 时间: 2025-07-22
 */
package com.hzbc.faceattendance.service.impl;

import com.alibaba.fastjson.JSON;
import com.hzbc.faceattendance.dto.ApiResponse;
import com.hzbc.faceattendance.dto.PasswordChangeRequest;
import com.hzbc.faceattendance.dto.WechatLoginRequest;
import com.hzbc.faceattendance.model.AdminUser;
import com.hzbc.faceattendance.model.SystemConfig;
import com.hzbc.faceattendance.repository.UserRepository;
import com.hzbc.faceattendance.security.JwtRequest;
import com.hzbc.faceattendance.security.JwtResponse;
import com.hzbc.faceattendance.service.IAuthService;
import com.hzbc.faceattendance.service.IWechatPushService;
import com.hzbc.faceattendance.utils.JwtUtil;
import com.hzbc.faceattendance.utils.UnionIdToOpenIdConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class AuthServiceImpl implements IAuthService {

    private final long EXPIRATIONMS = 3 * 60 * 60 * 1000;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UnionIdToOpenIdConverter unionIdToOpenIdConverter;
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private JwtUtil jwtUtil;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private SystemConfig systemConfig;
    @Autowired
    private IWechatPushService wechatPushService;

    @Override
    public ResponseEntity<?> createAuthenticationToken(JwtRequest authenticationRequest) {
        UserDetails userDetails;
        try {
            userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
            if (!passwordEncoder.matches(authenticationRequest.getPassword(), userDetails.getPassword())) {
                log.error("密码验证失败 用户名: {}", authenticationRequest.getUsername());
                return ResponseEntity.status(401).body("密码错误");
            }
        } catch (UsernameNotFoundException e) {
            log.error("用户不存在: {}", authenticationRequest.getUsername());
            return ResponseEntity.status(401).body("用户不存在");
        }
        userRepository.findByUsername(authenticationRequest.getUsername())
                .ifPresent(user -> {
                    if (user.getWcOpenId() == null || "".equals(user.getWcOpenId())) {
                        try {
                            saveWechatLoginInfo(user, authenticationRequest.getCode());
                        } catch (Exception e) {
                            log.error("微信校验失败");
                            e.printStackTrace();
                        }
                    }
                });
        final String token = jwtUtil.generateToken(userDetails);
        final String refreshToken = jwtUtil.generateRefreshToken(userDetails, EXPIRATIONMS);
        return ResponseEntity.ok(new JwtResponse(token, refreshToken));
    }

    private void saveWechatLoginInfo(AdminUser user, String code) throws Exception {
        String unionid = "";
        if (user.getUnionId() == null || "".equals(user.getUnionId())) {
            WechatAuthResult authResult = getUnionid(code);
            if (authResult == null) {
                return;
            }
//        String uniappOpenid = authResult.getOpenid(); //此处获取的是小程序的openid,暂时用不上这个，不做存储
            unionid = authResult.getUnionid(); //此处获取的是小程序的unionid
            user.setUnionId(unionid);
            userRepository.save(user);
        } else {
            unionid = user.getUnionId();
        }
        if(user.getRole()==2) {
            //1 .获取accessToken
            String accessToken = wechatPushService.getAccessToken();
            // 2. 分页获取所有用户的OpenID列表
            List<String> allOpenIds = unionIdToOpenIdConverter.getAllUserOpenIds(accessToken);
            if (allOpenIds.isEmpty()) {
                log.info("公众号没有关注用户");
                return;
            }
            log.info("获取到 " + allOpenIds.size() + " 个关注用户");
            // 3. 分批获取用户详细信息
            String matchedOpenId = unionIdToOpenIdConverter.findOpenIdByUnionId(accessToken, allOpenIds, unionid);
            if (matchedOpenId != null) {
                log.info("匹配成功！UnionID: " + unionid + " 对应的OpenID: " + matchedOpenId);
                user.setWcOpenId(matchedOpenId);
                userRepository.save(user);
            } else {
                log.info("该用户尚未关注公众号");
            }
        }
    }

    @Override
    public ResponseEntity<?> registerUser(AdminUser adminUser) {
        if (userRepository.findByUsername(adminUser.getUsername()).isPresent()) {
            return ResponseEntity.badRequest().body("Username is already taken!");
        }
        adminUser.setPassword(passwordEncoder.encode(adminUser.getPassword()));
        userRepository.save(adminUser);
        return ResponseEntity.ok("User registered successfully!");
    }

    @Override
    public ResponseEntity<?> wechatLogin(WechatLoginRequest request) {
        WechatAuthResult authResult = getWechatAuthInfo(request.getCode());
        String openid = authResult.getOpenid();
        String unionid = authResult.getUnionid();

//        //这部分代码是如果找不到则创建用户
//        AdminUser adminUser = userRepository.findByWcOpenId(openid)
//                .orElseGet(() -> {
//                    AdminUser newAdminUser = new AdminUser();
//                    newAdminUser.setWcOpenId(openid);
//                    newAdminUser.setUnionId(unionid);
//                    newAdminUser.setUsername("wechat_" + openid.substring(0, 8));
//                    newAdminUser.setPassword(passwordEncoder.encode("wechat_default_password"));
//                    return userRepository.save(newAdminUser);
//                });

        // 仅查询已有用户，不自动创建新用户
        AdminUser adminUser = userRepository.findByWcOpenId(openid)
                .orElseThrow(() -> new UsernameNotFoundException("该微信账号未绑定管理员账号，请先联系系统管理员进行绑定"));

        // 如果用户已存在但没有UnionId，补充更新
        if (adminUser.getUnionId() == null && unionid != null) {
            adminUser.setUnionId(unionid);
            userRepository.save(adminUser);
        }
        final UserDetails userDetails = userDetailsService.loadUserByUsername(adminUser.getUsername());
        final String token = jwtUtil.generateToken(userDetails);

        return ResponseEntity.ok(new JwtResponse(token));
    }

    @Override
    public ApiResponse<?> changePassword(PasswordChangeRequest request) {
        try {
            UserDetails userDetails = userDetailsService.loadUserByUsername(request.getUsername());
//            if (!passwordEncoder.matches(request.getOldPassword(), userDetails.getPassword())) {
//                return new ApiResponse<>(false, 401, "旧密码错误", null);
//            }
            AdminUser adminUser = userRepository.findByUsername(request.getUsername())
                    .orElseThrow(() -> new UsernameNotFoundException("用户不存在"));
            adminUser.setPassword(passwordEncoder.encode(request.getNewPassword()));
            userRepository.save(adminUser);
            return new ApiResponse<>(true, 0, "密码修改成功", null);
        } catch (UsernameNotFoundException e) {
            return new ApiResponse<>(false, 404, "用户不存在", null);
        }
    }

    private String getOpenidFromWechat(String code) {
        // 实现微信API调用获取openid
        return "mock_openid_" + code;
    }

    private WechatAuthResult getUnionid(String code) {
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + systemConfig.getUniAppId() +
                "&secret=" + systemConfig.getUniAppSecret() +
                "&js_code=" + code +
                "&grant_type=authorization_code";
        log.info("微信小程序认证接口调用url:{}", url);
        ResponseEntity<Map> response = restTemplate.getForEntity(url, Map.class);
        Map<String, Object> result = response.getBody();
        log.info("微信小程序认证接口调用成功,结果:{}", JSON.toJSONString(result));
        if (result == null || result.containsKey("errcode")) {
            String errMsg = (String) result.get("errmsg");
            log.error("获取微信用户信息失败: errCode:" + result.get("errcode  ") + "errMsg:" + errMsg);
            return null;
        }
        WechatAuthResult authResult = new WechatAuthResult();
        authResult.setOpenid((String) result.get("openid"));
        authResult.setUnionid((String) result.get("unionid"));
        authResult.setSessionKey((String) result.get("session_key"));
        return authResult;

    }

    // ... existing code ...
    private WechatAuthResult getWechatAuthInfo(String code) {
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + systemConfig.getWechatAppId() +
                "&secret=" + systemConfig.getWechatAppSecret() +
                "&code=" + code +
                "&grant_type=authorization_code";
        log.info("微信认证接口调用url:{}", url);
        try {
            ResponseEntity<Map> response = restTemplate.getForEntity(url, Map.class);
            Map<String, Object> result = response.getBody();
            log.info("213微信认证接口调用成功,结果:{}", JSON.toJSONString(result));
            if (result == null || result.containsKey("errcode")) {
                String errMsg = (String) result.get("errmsg");
                throw new RuntimeException("获取微信用户信息失败: " + errMsg);
            }

            WechatAuthResult authResult = new WechatAuthResult();
            authResult.setOpenid((String) result.get("openid"));
            authResult.setUnionid((String) result.get("unionid"));
            authResult.setSessionKey((String) result.get("session_key"));

            return authResult;
        } catch (Exception e) {
            log.error("微信认证接口调用失败", e);
            throw new RuntimeException("微信登录失败");
        }
    }

    // ... existing code ...
    private static class WechatAuthResult {
        private String openid;
        private String unionid;
        private String sessionKey;

        // Getters and setters
        public String getOpenid() {
            return openid;
        }

        public void setOpenid(String openid) {
            this.openid = openid;
        }

        public String getUnionid() {
            return unionid;
        }

        public void setUnionid(String unionid) {
            this.unionid = unionid;
        }

        public String getSessionKey() {
            return sessionKey;
        }

        public void setSessionKey(String sessionKey) {
            this.sessionKey = sessionKey;
        }
    }
}